类是 C++ 的一大特色,但是只知道类却不会类的继承是没有太大意义的。今天,我们就来聊一下类的继承。
类,即 class,与结构体 struct 类似,同时也添加了一些新的功能。
类中的元素分 public、protected 和 private 三种,在继承时有所体现:
| 继承类型 | 基类 public 元素在 派生类的类别 | 基类 protected 元素在 派生类的类别 | 基类 private 元素在 派生类的类别 |
|---|---|---|---|
| public 继承 | public | protected | 不继承 |
| protected 继承 | protected | protected | 不继承 |
| private 继承 | private | private | 不继承 |
注意继承的种类改变不了以下几点:
- private 成员只能在类内及友元中被访问,无法被派生类访问;
- protected 成员可以在派生类访问。
下面看一个具体的例子:
//By: Luogu@rui_er(122461)
#include <bits/stdc++.h>
using namespace std;
class A { // 定义基类 A
public:
int a;
A() {
a = 1;
b = 2;
c = 3;
d = 4;
}
void print() {
cout<<a<<endl; // 正确,类中成员
cout<<b<<endl; // 正确,类中成员
cout<<c<<endl; // 正确,类中成员
cout<<d<<endl; // 正确,类中成员
}
public:
int b;
protected:
int c;
private:
int d;
};
class B : public A { // 从 A 通过 public 继承得到派生类 B
public:
int a;
B(int x) {
A();
a = x;
}
void print() {
cout<<a<<endl; // 正确,类中成员
cout<<b<<endl; // 正确,在基类中是 public 成员,在派生类依然是 public 成员
cout<<c<<endl; // 正确,在基类中是 protected 成员,在派生类依然是 protected 成员
cout<<d<<endl; // 错误,基类的 private 成员不能被继承
}
};
int main() {
B b(5);
cout<<b.a<<endl; // 正确,类中 public 成员
cout<<b.b<<endl; // 正确,继承为 public 成员
cout<<b.c<<endl; // 错误,继承为 protected 成员,不能在类外访问
cout<<b.d<<endl; // 错误
return 0;
}
这里是 public 继承,另外两种继承可以以此类推。
虚拟继承
在类 A 中的函数 f() 继承到 B 中需要重写,怎么办?
! 如果只是想根据基类函数加一些代码:
class A {
public:
void f() {
puts("A");
}
};
class B : public A {
public:
void f() {
A::f(); // 调用基类的 f() 函数
puts("B"); // 需要额外添加的代码
}
};
这里基类指针可以指向派生类的对象:
class A {
public:
int a;
};
class B : public A {
public:
int b;
};
int main() {
B b;
b.a = 1;
b.b = 2;
A* p = &b;
printf("%d\n", p->a);
return 0;
}
! 问题
class A {
public:
void f() {
puts("A");
}
};
class B : public A {
public:
void f() {
puts("B");
}
};
int main() {
B b;
A* p = &b;
p->f(); // 这一行
}
程序中的 p->f() 到底指哪一个?
! 继承时重写函数
如果一个函数需要被重写,在基类中应声明为 virtual,此时将调用子类的函数。
class A {
public:
virtual void f() {
puts("A");
}
};
class B : public A {
public:
void f() {
puts("B");
}
};
int main() {
B b;
A* p = &b;
p->f(); // 这一行
}
继承中的构造、析构函数问题
class A {
public:
A() : a(0), b(0) {
puts("A()");
}
A(int x, int y) : a(x), b(y) {
puts("A(x, y)");
}
~A() {
puts("~A()");
}
private:
int a, b;
};
class B : public A {
public:
B() : A(0, 1) {
puts("B()");
}
~B() {
puts("~B()");
}
};
int main() {
A* p = new B();
delete p;
}
在这个程序中,delete p 可能导致程序出错甚至崩溃,这里需要将 ~A() 声明为 virtual:
virtual ~A()
多重继承
class father {/*Do somthing..*/};
class mother {/*Do something..*/};
class son : public father, public mother {/*Do somthing..*/};
注意这里如果 father 和 mother 中出现同名变量可能导致错误。